package com.tencreat.framework.aspectj;

import com.tencreat.common.annotation.Limit;
import com.tencreat.common.core.HttpResult;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Slf4j
@Aspect
@Component
public class LimitAop {

    @Autowired
    RedisTemplate redisTemplate;

    @Around("@annotation(com.tencreat.common.annotation.Limit)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //拿limit的注解
        Limit limit = method.getAnnotation(Limit.class);

        String limitKey = limit.key();
        if (StringUtil.isBlank(limitKey)) {
            // 默认使用方法名作为key
            limitKey = method.getName();
        }
        Long increment = 1L;
        if (!redisTemplate.hasKey(limitKey)) {
            // 初始化，存放令牌桶容量
            redisTemplate.opsForValue().set(limitKey, 1, limit.timeout(), limit.timeunit());
        } else {
            increment = redisTemplate.opsForValue().increment(limitKey);
        }
        if (increment > limit.times()) {
            return HttpResult.error(limit.msg());
        }
        return joinPoint.proceed();
    }
}
